﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SharpMUD.Framework.Workflow.Generic;
using SharpMUD.Framework.Net;
using SharpMUD.Framework.Net.Telnet;
using SharpMUD.Framework.Services.Net;

namespace SharpMUD.Framework.Services.Telnet
{
    public partial class TelnetServer
        :   IControlledExecution,
            IPulseDependent,
            IDisposable
    {

        #region IControlledExecution Members

        public void Start()
        {
            if (this.ExecutionStatus != ExecutionStatusTokens.Initialized)
                throw new InvalidExecutionStatusTransitionException(this.ExecutionStatus, ExecutionStatusTokens.Starting);
            this.ExecutionStatus = ExecutionStatusTokens.Starting;
            log.Info(this.ExecutionStatus.ToString());

            this.StartListeners();

            this.ExecutionStatus = ExecutionStatusTokens.Running;
            log.Info(this.ExecutionStatus.ToString());
        }

        public void Stop()
        {
            if (this.ExecutionStatus != ExecutionStatusTokens.Running)
                throw new InvalidExecutionStatusTransitionException(this.ExecutionStatus, ExecutionStatusTokens.Stopping);
            this.ExecutionStatus = ExecutionStatusTokens.Stopping;
            log.Info(this.ExecutionStatus.ToString());

            this._PulseCancellationTokenSource.Cancel();
            this.StopListeners();
            this.StopSessions();

            this.ExecutionStatus = ExecutionStatusTokens.Stopped;
            log.Info(this.ExecutionStatus.ToString());
        }

        #endregion

        #region IHasExecutionStatus Members

        private IExecutionStatusToken _ExecutionStatus;
        public IExecutionStatusToken ExecutionStatus
        {
            get
            {
                return _ExecutionStatus;
            }
            private set
            {
                IExecutionStatusToken oldValue = _ExecutionStatus;
                if (oldValue != value)
                {
                    _ExecutionStatus = value;
                    if (ExecutionStatusChanged != null)
                        ExecutionStatusChanged(this, new ValueChangedEventArgs<IExecutionStatusToken>(oldValue, value));
                }
            }
        }

        public event EventHandler<ValueChangedEventArgs<IExecutionStatusToken>> ExecutionStatusChanged;

        #endregion

        #region IPulseDependent Members

        public void Pulse()
        {
            if (this.ExecutionStatus == ExecutionStatusTokens.Running)
            {
                this.PulseListeners();
                this.PulseSessions();
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.ExecutionStatus = ExecutionStatusTokens.Disposing;

            this.DisposeListeners();
            this.DisposeSessions();

            this.ExecutionStatus = ExecutionStatusTokens.Disposed;

        }

        #endregion

        private void DetectApplicableNetworkFilterServices()
        {
            lock (this._DetectedFilterServices)
            {
                this._DetectedFilterServices.Clear();
                this._DetectedFilterServices.AddRange(
                        this.ServicesHost.Services.Where(s=>s is INetworkConnectionFilterService<TelnetSession>)
                        .Select(s=>s as INetworkConnectionFilterService<TelnetSession>)
                    );
            }
        }
    }
}
